package com.DosonLeung.homeschoolcommunication.Services;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.DosonLeung.homeschoolcommunication.App.SystemApplication;
import com.DosonLeung.homeschoolcommunication.Constant.SystemConstant;
import com.DosonLeung.homeschoolcommunication.Constant.UserConstant;
import com.DosonLeung.homeschoolcommunication.SQLite.ChatsDB;
import com.DosonLeung.homeschoolcommunication.SQLite.MembersDB;
import com.DosonLeung.homeschoolcommunication.Utils.NotificationUtil;
import com.DosonLeung.homeschoolcommunication.Utils.StorageUtil;
import com.DosonLeung.homeschoolcommunication.Utils.TimeUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

public class MainService extends Service {

    final private Service self = this;
    SystemApplication app;
    //与MainActivity通讯用的Binder;
    MainBinder mainBinder;
    //socket
    SocketService socketService;
    //防止高并发
    TimeUtil.Avail avail;
    //聊天记录数据库
    ChatsDB chatsDB;
    //联系人数据库
    MembersDB membersDB;
    //发送消息给MainActivit的Handler
    private Handler mainHandler;
    //聊天目标的uid
    private String targetId = "";
    //当前聊天窗口状态
     private boolean chattingWindowStatus = false;
     //当前MainActivity状态
     private boolean mainActivityStatus = false;

    /**
    * 接收其他Activity消息的Handler
    * 0x100 来自MainActivity的握手信号
    * 0x101 来自ChatActivity的握手信号
    * 0x102 表示已经获取到了用户信息,可以启动Socket了
    * 0x200 表示了Socket接收了新的聊天信息
    * 0x201 表示用户打开了聊天窗口，并带来了对方的uid和用户的uid
    * 0x202 表示用户点击了发送消息，通过msg带来了消息(类型：text)
    * 0x203 表示用户点击了发送消息，通过msg带来了消息(类型：image)
    * 0x204 表示用户点击了发送消息，通过msg带来了消息(类型：audio)
    * 0x205 表示Socket消息发送成功(text类型)
    * 0x206 表示Socket消息发送成功(image类型)
    * 0x207 表示Socket消息发送成功(audio类型)
    * 0x208 表示socket下载音频文件成功
    * 0x400 表示用户关闭了聊天窗口，清空targetId
    * 0x404 表示Socket消息发送失败
    * 0x408 表示Socket下载音频失败
    * 0x444 表示MainActivity准备结束生命了，自己也命不久矣
    * 0x500 表示MainActivity不可更新视图
    * 0x501 表示ChatActivity不可更新视图
    * 0x502 表示MainActivity可更新视图
    * 0x503 表示ChatActivity可更新视图
    * **/
    private final Handler serviceHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData();
            HashMap<String,String> item;
            switch (msg.what) {
                case 0x100:
                    if (getMainHandler()) {//当收到来自MainActivity的握手信号后，MainActiviy已经在MainBinder里放置了MainHnadler
                        Log.e("Service", "mainActivity get serviceHandler successfully!");
                        mainHandler.sendEmptyMessage(0x100);
                    } else {
                        Log.e("Servce", "can't get Main Handler!");
                    }
                    break;
                case 0x101:
                    if (getChatHandler()) {//同上
                        mainBinder.getChatHandler().sendEmptyMessage(0x100);
                        Log.e("Service", "chatActivity get serviceHandler successfully!");
                    } else {
                        Log.e("Servce", "can't get Chat Handler!");
                    }
                    break;
                case 0x102: //所有信息初始化完毕，但是不一定有个人信息
                    initSocket();
                    break;
                case 0x200: {//收到新的聊天消息(文字或者图像，语音在下载成功后会到达此处）
                    HashMap<String, String> data = socketService.getData();
                    if (save(data)) {
                        Log.e("targetId",targetId);
                        if(data!=null)
                            refreshViews(data.get("content"));
                        socketService.notify(true);
                    } else {
                        socketService.notify(false);
                    }
                    break;
                }
                case 0x201: {//用户发送了新消息
                    bundle = msg.getData();
                    targetId = bundle.getString("targetId");//群发为"groupchat"
                    Log.e("Service", "new ChatActivity");
                    break;
                }
                case 0x202: {//请求发送text文本信息
                    bundle = msg.getData();
                    if(targetId.equals("groupchat"))//这里发送文本信息
                        sendGroupData(bundle);
                    else
                        sendData(bundle);
                    break;
                }
                case 0x203: {//请求发送image文本信息，先上传，再发送
                    bundle = msg.getData();
                    upLoadImage(bundle);
                    break;
                }
                case 0x204: {//请求发送audio文本信息,先上传，再发送
                    bundle = msg.getData();
                    upLoadAudio(bundle);
                    break;
                }
                case 0x205://text类型信息发送成功
                    if (getChatHandler())
                        mainBinder.getChatHandler().sendEmptyMessage(0x205);
                    break;
                case SystemConstant.UPLOAD_IMAGE_SUCCESS:
                    bundle = msg.getData();
                    item = updateDB(socketService.take(bundle.getString("name")));
                    if(targetId.equals("groupchat"))
                        sendGroupData(item);
                    else
                        sendData(item);
                    if (getChatHandler())
                        mainBinder.getChatHandler().sendEmptyMessage(SystemConstant.UPLOAD_IMAGE_SUCCESS);
                    break;
                case SystemConstant.UPLOAD_AUDIO_SUCCESS:
                    bundle = msg.getData();
                    item = updateDB(socketService.take(bundle.getString("name")));
                    if(targetId.equals("groupchat"))
                        sendGroupData(item);
                    else
                        sendData(item);
                    if (getChatHandler())
                        mainBinder.getChatHandler().sendEmptyMessage(SystemConstant.UPLOAD_IMAGE_SUCCESS);
                    break;
                case SystemConstant.DOWNLOAD_AUDIO_SUCCESS:
                    Bundle data = msg.getData();//下载音频成功
                    String url = data.getString("url");
                    String filePath = data.getString("filepath");
                    boolean status = data.getBoolean("status");
                    socketService.moveDLQ2DQ(url,filePath,status);
                    break;
                case 0x400:
                    targetId = "";
                    break;
                case 0x404:
                    if (getChatHandler())
                        mainBinder.getChatHandler().sendEmptyMessage(0x404);
                    else
                        Toast.makeText(self, "消息发送失败，原因网络超时", Toast.LENGTH_SHORT).show();
                    break;
                case 0x444:
                    if(socketService!=null)
                        socketService.notify(false);//此处Socket会暂停一切任务，并准备自杀
                    self.stopSelf();
                    break;
                case 0x500:
                    mainActivityStatus = false;
                    break;
                case 0x501:
                    chattingWindowStatus = false;
                    break;
                case 0x502:
                    mainActivityStatus = true;
                    break;
                case 0x503:
                    chattingWindowStatus = true;
                    break;
                case SystemConstant.LOG_STRANGE:
                    if(mainHandler!=null)
                        mainHandler.sendEmptyMessage(SystemConstant.LOG_STRANGE);
            }
        }
    };

    @Override
    public void onCreate(){
        super.onCreate();
        avail = TimeUtil.getAvail();
        app = (SystemApplication)getApplication();
        mainBinder = new MainBinder(serviceHandler);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mainBinder;
    }

    private boolean getMainHandler() {
        try {
            mainHandler = mainBinder.getMainHandler();
            return mainHandler != null;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    private boolean getChatHandler() {
        try {
            return mainBinder.getChatHandler() != null;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    //判断当前是否有聊天窗口
    private boolean checkChattingOrNot(){
        return mainBinder.getChatHandler() != null;
    }

    //初始化Socket
    private void initSocket(){
        socketService = new SocketService(this, serviceHandler);
        socketService.notify(true);
        socketService.start();
        socketService.getHistory();
    }

    //通知所有的视图刷新
    private void refreshViews(String content){
        if(checkChattingOrNot()) {
            if(chattingWindowStatus) {//如果在聊天窗口状态下
                if(!targetId.equals("groupchat"))
                    mainBinder.getChatHandler().sendEmptyMessage(0X200);
            }else{//不在聊天窗口状态下
                notifyUser(content,"ChatActivity");
            }
        }else if(mainActivityStatus){
            if(avail.isAvail())
                mainHandler.sendEmptyMessage(0x201);
        }else{
            notifyUser(content,"MainActivity");
        }
    }

    //文本保存消息至本地
    private boolean save(HashMap<String, String> data){
        try {
            if(data!=null) {
                String length = data.get("length");//uid发送方的uid
                String targetId = (length.equals(""))?data.get("uid"):length+UserConstant.USER_ID;//cid是否存在？是，存放cid+uid,否,存放uid
                if ((targetId != null) && (!targetId.equals(""))) {
                    HashMap<String, String> chatItem = new HashMap<String, String>();
                    HashMap<String, String> memberItem = new HashMap<String, String>();
                    membersDB = new MembersDB(self, StorageUtil.getChatDir().toString() + "/" + "members.db3", 1);
                    chatItem.put("uid", targetId);
                    chatItem.put("contentType", data.get("contentType"));//这里需要解析下类型
                    chatItem.put("time", data.get("time"));//文字的时间格式
                    chatItem.put("content", data.get("content"));
                    chatItem.put("url", data.get("url"));
                    chatItem.put("length", length);
                    chatItem.put("contentLevel",data.get("level"));//新增字段，可有可无
                    chatItem.put("extra",data.get("extra"));//新增字段，可有可无
                    memberItem.put("uid", targetId);
                    memberItem.put("lasttime", data.get("time"));
                    memberItem.put("lastnote", data.get("content"));
                    memberItem.put("lastnotetype", data.get("contentType"));
                    chatsDB = new ChatsDB(self, StorageUtil.getChatDir().toString() + "/" + targetId + ".db3", targetId, 1);
                    chatsDB.insertChattingData(chatItem);
                    chatsDB.close();
                    membersDB.updateMembersPart(memberItem);
                    membersDB.close();
                    SystemConstant.addNewInRegister(targetId);//消息计数器加1
                } else {
                    Log.e("Service", "收到了一个uid不在数据库里的消息!");
                }
            }
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }finally {
            if(membersDB!=null)
            membersDB.close();
            if(chatsDB!=null)
            chatsDB.close();
        }
    }


    protected HashMap<String,String> updateDB(HashMap<String,String> data){
        try {
            if(data!=null) {
                String targetId = data.get("uid");
                if ((targetId != null) && (!targetId.equals(""))) {
                    HashMap<String, String> chatItem = new HashMap<String, String>();
                    HashMap<String, String> memberItem = new HashMap<String, String>();
                    chatItem.put("uid", data.get("uid"));
                    chatItem.put("contentType", data.get("type"));//这里需要解析下类型
                    chatItem.put("time", TimeUtil.patchTime(data.get("time")));//photo HH:MM:ss radio HH:MM:ss
                    chatItem.put("content", data.get("content"));
                    chatItem.put("url", data.get("url"));
                    chatItem.put("length", data.get("length"));
                    chatItem.put("contentLevel",data.get("msg_type"));//新增字段，可有可无
                    chatItem.put("extra",data.get("sender_uid"));//新增字段，可有可无
                    memberItem.put("uid", data.get("uid"));
                    memberItem.put("lasttime", TimeUtil.patchTime(data.get("time")));
                    memberItem.put("lastnote", data.get("content"));
                    memberItem.put("lastnotetype", data.get("contentType"));
                    chatsDB = new ChatsDB(self, StorageUtil.getChatDir().toString() + "/" + targetId + ".db3", targetId, 1);
                    chatsDB.updateChattingData(chatItem);
                    chatsDB.close();
                    membersDB = new MembersDB(self, StorageUtil.getChatDir().toString() + "/" + "members.db3", 1);
                    membersDB.updateMembersPart(memberItem);
                    membersDB.close();
                } else {
                    Log.e("Service", "收到了一个uid不在数据库里的消息!");
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            if(membersDB!=null)
                membersDB.close();
            if(chatsDB!=null)
                chatsDB.close();
        }
        return data;
    }

    //通过socket发送个人消息（图片，语音）
    private void sendData(HashMap<String,String> item){
        JSONObject data = new JSONObject();
        try {
            data.put("type",item.get("type"));
            data.put("content",item.get("content"));
            data.put("time", item.get("time"));
            data.put("cid",item.get("cid"));
            data.put("uid",item.get("uid"));
            data.put("sender_name",item.get("sender_name"));
            data.put("sender_uid",item.get("sender_uid"));
            data.put("msg_type",item.get("msg_type"));
            socketService.sendData(data);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        // type -- 消息类型（text、image、audio）
        // content -- 消息内容（如果类型为text就是文字内容，否则为资源url）
        // time -- 时间（格式按HH:mm:ss）
        // cid -- 如果消息为班级群发消息，这里是班级的id，否则为空字符串
        // uid -- 如果消息为私聊消息，这里是接收者的id，否则为空字符串，cid和uid必有一个为空字符串另一个不为空字符串
        // sender_name -- 发送者的名字
        // sender_uid -- 发送者的uid
        // 以上所有消息生成一个JSONObject，然后调用以下方法
        // socketService.sendData(data);
    }

    //通过socket发送个人消息（图片，语音）
    private void sendGroupData(HashMap<String,String> item){
        int size = app.getTargetList().size();
        JSONObject data = new JSONObject();
        try {
            data.put("type",item.get("type"));
            data.put("content",item.get("content"));
            data.put("time", item.get("time"));
            data.put("cid",item.get("cid"));
            //data.put("uid",bundle.getString("uid"));target:"groupchat"
            data.put("sender_name",item.get("sender_name"));
            data.put("sender_uid",item.get("sender_uid"));
            data.put("msg_type",item.get("msg_type"));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        for(int i = 0;i < size;i++){
            try {
                data.remove("uid");
                data.put("uid",app.getTargetList().get(i));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            socketService.sendData(data);
        }
    }

    //通过socket发送个人消息(文本)
    private void sendData(Bundle bundle){
        JSONObject data = new JSONObject();
        try {
            data.put("type",bundle.getString("contentType"));
            data.put("content",bundle.getString("content"));
            data.put("time", TimeUtil.simplifyTime(bundle.getString("contentTime")));
            data.put("cid",bundle.getString("cid"));
            data.put("uid",bundle.getString("uid"));
            data.put("sender_name",bundle.getString("sender_name"));
            data.put("sender_uid",bundle.getString("sender_uid"));
            data.put("msg_type",bundle.getString("contentLevel"));
            socketService.sendData(data);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        // type -- 消息类型（text、image、audio）
        // content -- 消息内容（如果类型为text就是文字内容，否则为资源url）
        // time -- 时间（格式按HH:mm:ss）
        // cid -- 如果消息为班级群发消息，这里是班级的id，否则为空字符串
        // uid -- 如果消息为私聊消息，这里是接收者的id，否则为空字符串，cid和uid必有一个为空字符串另一个不为空字符串
        // sender_name -- 发送者的名字
        // sender_uid -- 发送者的uid
        // 以上所有消息生成一个JSONObject，然后调用以下方法
        // socketService.sendData(data);
    }

    //通过socket群发消息(文本)
    private void sendGroupData(Bundle bundle){
        int size = app.getTargetList().size();
        JSONObject data = new JSONObject();
        try {
            data.put("type",bundle.getString("contentType"));
            data.put("content",bundle.getString("content"));
            data.put("time", TimeUtil.simplifyTime(bundle.getString("contentTime")));
            data.put("cid",bundle.getString("cid"));//""
            //data.put("uid",bundle.getString("uid"));target:"groupchat"
            data.put("sender_name",bundle.getString("sender_name"));
            data.put("sender_uid",bundle.getString("sender_uid"));//USER_ID
            data.put("msg_type",bundle.getString("contentLevel"));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        for(int i = 0;i < size;i++){
            try {
                data.remove("uid");
                data.put("uid",app.getTargetList().get(i));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            socketService.sendData(data);
        }
    }

    private void upLoadImage(Bundle bundle){
        HashMap<String,String> data = new HashMap<String,String>();
        data.put("type",bundle.getString("contentType"));
        data.put("content",bundle.getString("content"));
        data.put("url",bundle.getString("url"));
        data.put("time", TimeUtil.simplifyTime(bundle.getString("contentTime")));
        data.put("cid",bundle.getString("cid"));
        data.put("uid",bundle.getString("uid"));
        data.put("sender_name",bundle.getString("sender_name"));
        data.put("sender_uid",bundle.getString("sender_uid"));
        data.put("msg_type",bundle.getString("contentLevel"));
        socketService.upLoadImage(data);
    }

    private void upLoadAudio(Bundle bundle){
        HashMap<String,String> data = new HashMap<String,String>();
        data.put("type",bundle.getString("contentType"));
        data.put("content",bundle.getString("content"));
        data.put("url",bundle.getString("url"));
        data.put("time", TimeUtil.simplifyTime(bundle.getString("contentTime")));
        data.put("cid",bundle.getString("cid"));
        data.put("uid",bundle.getString("uid"));
        data.put("sender_name",bundle.getString("sender_name"));
        data.put("sender_uid",bundle.getString("sender_uid"));
        data.put("msg_type",bundle.getString("contentLevel"));
        socketService.upLoadAudio(data);
    }

    //收到新消息后，如果程序不在前台，则创建通知提醒
    private void notifyUser(String text,String activity){
        if(SystemConstant.autonotify)
            NotificationUtil.CreateInform(self,activity,"你有新的家校通消息","家校通",text,101);
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
    }
}
